package cn.lg.soar.database.base.service;

import cn.lg.soar.common.util.AssertUtil;
import cn.lg.soar.database.base.entity.INumberTreeEntity;
import cn.lg.soar.database.base.enums.TreePositionRelationEnum;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

import java.io.Serializable;
import java.util.List;

/**
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public interface INumberTreeService<T extends INumberTreeEntity> extends ITreeService<T> {

    /**
     * 节点移动
     * @param id 节点id
     * @param targetId 要移动到的目标节点
     * @param relation 移动到目标节点的什么位置（前面、后面、作为目标节点的孩子）
     */
    void move(Serializable id, Serializable targetId, TreePositionRelationEnum relation);

    /**
     * 节点移动
     * @param oldLeftNo
     * @param oldRightNo
     * @param distance 移动的距离（"distance = 新左值 - 旧左值" 或者  "distance = 新右值 - 旧右值"）
     */
    void move(int oldLeftNo, int oldRightNo, int distance);

    /**
     * 节点移动
     * @param id 节点id
     * @param distance 移动的距离（"distance = 新左值 - 旧左值" 或者  "distance = 新右值 - 旧右值"）
     */
    default void move(Serializable id, int distance) {
        T entity = getById(id);
        AssertUtil.notNull(entity, "数据不存在");
        move(entity.getLeftNo(), entity.getRightNo(), distance);
    }

    /**
     * 节点移动
     * @param id 节点id
     * @param newLeftNo 节点新的左值
     */
    default void moveByLeft(Serializable id, int newLeftNo) {
        T entity = getById(id);
        AssertUtil.notNull(entity, "数据不存在");
        int oldLeftNo = entity.getLeftNo();
        move(oldLeftNo, entity.getRightNo(), newLeftNo - oldLeftNo);
    }

    /**
     * 节点移动
     * @param id 节点id
     * @param newRightNo 节点新的右值
     */
    default void moveByRight(Serializable id, int newRightNo) {
        T entity = getById(id);
        AssertUtil.notNull(entity, "数据不存在");
        int oldRightNo = entity.getRightNo();
        move(entity.getLeftNo(), oldRightNo, newRightNo - oldRightNo);
    }

    /**
     * 获取后辈、下级(不包含自己)
     * @param leftNo 节点左值
     * @param rightNo 节点右值
     * @return
     */
    default List<T> getInferiorsList(int leftNo, int rightNo) {
        return list(
                Wrappers.<T>lambdaQuery(getEntityClass())
                        .gt(T::getLeftNo, leftNo)
                        .lt(T::getRightNo, rightNo)
        );
    }

    /**
     * 获取后辈、下级(不包含自己)
     * @param id 节点id
     * @return
     */
    default List<T> getInferiorsList(Serializable id) {
        T t = getById(id);
        return getInferiorsList(t.getLeftNo(), t.getRightNo());
    }

    /**
     * 获取自己和下级
     * @param leftNo 节点左值
     * @param rightNo 节点右值
     * @return
     */
    default List<T> getInferiorsAndSelfList(int leftNo, int rightNo) {
        return list(
                Wrappers.<T>lambdaQuery(getEntityClass())
                        .ge(T::getLeftNo, leftNo)
                        .le(T::getRightNo, rightNo)
        );
    }

    /**
     * 获取自己和下级
     * @param id 节点id
     * @return
     */
    @Override
    default List<T> getInferiorsAndSelfList(Long id) {
        T t = getById(id);
        List<T> list = getInferiorsList(t.getLeftNo(), t.getRightNo());
        list.add(t);
        return list;
    }

    /**
     * 获取祖先列表(不包含自己)
     * @param leftNo 节点左值
     * @param rightNo 节点右值
     * @return
     */
    default List<T> getAncestorList(int leftNo, int rightNo) {
        return list(
                Wrappers.<T>lambdaQuery(getEntityClass())
                        .lt(T::getLeftNo, leftNo)
                        .gt(T::getRightNo, rightNo)
        );
    }

    /**
     * 获取祖先列表(不包含自己)
     * @param id 节点id
     * @return
     */
    default List<T> getAncestorList(Serializable id) {
        T t = getById(id);
        return getAncestorList(t.getLeftNo(), t.getRightNo());
    }

    /**
     * 获取节点路径：【根节点，n个中间节点，子节点】
     * @param leftNo 节点左值
     * @param rightNo 节点右值
     * @return
     */
    default List<T> getNodePathList(int leftNo, int rightNo) {
        return list(
                Wrappers.<T>lambdaQuery()
                        .le(T::getLeftNo, leftNo)
                        .ge(T::getRightNo, rightNo)
        );
    }

    /**
     * 获取节点路径：【根节点，n个中间节点，子节点】
     * @param id 当前节点id
     * @return
     */
    default List<T> getNodePathList(Long id) {
        T t = getById(id);
        List<T> list = getAncestorList(t.getLeftNo(), t.getRightNo());
        list.add(t);
        return list;
    }

    /**
     * 获取节点所在层级 (0是顶级)
     * @param leftNo 节点左值
     * @param rightNo 节点右值
     * @return
     */
    default long getNodeLevel(int leftNo, int rightNo) {
        return count(
                Wrappers.<T>lambdaQuery(getEntityClass())
                        .lt(T::getLeftNo, leftNo)
                        .gt(T::getRightNo, rightNo)
        );
    }

    /**
     * 获取节点所在层级 (0是顶级)
     * @param id 节点id
     * @return
     */
    default long getNodeLevel(Serializable id) {
        T data = getById(id);
        return getNodeLevel(data.getLeftNo(), data.getRightNo());
    }

}
